import React, { useEffect, useState, useImperativeHandle, useRef } from 'react'
import './index.less'
import initGraph from './graph.js'
import StencilPannel from '../stencil-pannel/index.jsx'
import NodeAttrTable from '../node-attr-table/index.jsx'
import { EVENT_SELECTED_NODE, EVENT_ADD_NODE, EVENT_REMOVE_NODE, EVENT_EDGE_CONNECTION, EVENT_REMOVE_EDGE, EVENT_MOVE_NODE  } from './event.js'
import CanvasContextmenu from '../canvas-contextmenu/index.jsx'
import { addInfo, updateContentById, delInfo, line, changNotes, delLine, sortNode } from '@/api/project-flow.js'
import { NODE_TYPE_DRAG } from '@/utils/constant.js'
import CanvasPage from '@/components/canvas-page'
import { ContainerLayout, CommonTitle } from '@/components'
import ChildrenTree from '../children-tree/index.jsx'
import { Carousel } from 'antd'

// 1测试用例 2 分支 3 流程
export const FlowCanvas = React.forwardRef((props, ref) => {
  const {
    headerLeftContent,
    pageTitle,
    toolbar,
    menuConifg,
    modelData,
    stencilPannelList,
    treePanel,
    contentPanel,
    afterGraphInit,
    showChildren, // 是否显示children面板
  } = props
  const [graph, setGraph] = useState(null)
  const [currentNode, setCurrentNode] = useState(null)
  const [attrNodeData, setAttrNodeData] = useState({})
  const carouselRef = useRef(null)

  const comItems = stencilPannelList.map((item) => {
    return (
      <StencilPannel
        key={item.typeCode}
        typeCode={item.typeCode}
        templateType={item.templateType}
        templateName={item.templateName}
        graph={graph}
      />
    )
  })

  const nodeClick = (node) => {
    setCurrentNode(node)
    setAttrNodeData(!node ? null : {
      canvasType: modelData.canvasType,
      typeCode: node.data.typeCode,
      nodeId: node.id,
      nodeName: node.data.templateName,
    })
  }

  const convertNodeData = (node) => {
    return {
      id: node.data.id,
      typeCode: node.data.typeCode,
      nodeType: NODE_TYPE_DRAG,
      templateId: node.data.template_id,
      templateIcon: node.data.template_icon,
      templateName: node.data.template_name,
      templateCode: node.data.template_code,
      templateType: node.data.template_type,
      typeId: node.data.type_id,
    }
  }

  const nodeAdded = (event) => {
    const { node } = event
    if (!node && !node.data && node.data.nodeType != NODE_TYPE_DRAG) {
      return
    }
    node.data = convertNodeData(node)
    addInfo({
      toolId: node.data.id,
      nodeId: node.id,
      projectId: modelData.projectId,
      type: modelData.canvasType,
      branchOrInstanceId: modelData.id,
      content: JSON.stringify(graph.toJSON())
    }).then(() => {
      console.log('添加成功')
    })
  }

  const nodeDel = (event) => {
    const { node } = event
    delInfo({
      nodeId: node.id,
      type: modelData.canvasType,
      branchOrInstanceId: modelData.id,
      content: JSON.stringify(graph.toJSON())
    }).then(() => {
      console.log('删除成功')
    })
  }

  const edgeDel = (event) => {
    const { edge } = event
    delLine({
      sourceNodeId: edge.source.cell,
      targetNodeId: edge.target.cell,
      type: modelData.canvasType,
      branchOrInstanceId: modelData.id,
      content: JSON.stringify(graph.toJSON())
    }).then(() => {
      console.log('删除成功')
    })
  }

  const edgeConnected = (event) => {
    const {source, target} = event.edge
    line({
      sourceNodeId: source.cell,
      targetNodeId: target.cell,
      type: modelData.canvasType,
      branchOrInstanceId: modelData.id,
      content: JSON.stringify(graph.toJSON())
    }).then(res => {
      console.log('连线成功')
    })
  }

  const onSortNode = (data) => {
    sortNode({
      ...data,
      type: modelData.canvasType,
      branchOrInstanceId: modelData.id,
      content: JSON.stringify(graph.toJSON())
    }).then(res => {
      console.log('排序成功')
    })
  }

  const onChangNotes = (nodeId, notes) => {
    changNotes({
      nodeId,
      notes,
      type: modelData.canvasType,
      branchOrInstanceId: modelData.id,
      content: JSON.stringify(graph.toJSON())
    }).then(() => {
      console.log('修改注释成功')
    })
  }

  const nameChange = (nodeData, name) => {
    if (nodeData.nodeId != currentNode.id) {
      return
    }

    let node = graph.getCellById(currentNode.id)
    node.data.templateName = name
    node.setAttrs({
      label: {
        textWrap: {
          text: name,
        },
      },
    })
    setCurrentNode({ ...node, data: node.data })
    onSortNode({})
  }

  useEffect(() => {
    let tempGraph = initGraph({
      container: document.getElementById('graph-container'),
    })
    setGraph(tempGraph)
  }, [])

  useEffect(() => {
    if (graph) {
      graph.clearCells({silent: true})
      if (modelData) {
        graph.off(EVENT_ADD_NODE)
        graph.off(EVENT_SELECTED_NODE)
        graph.off(EVENT_REMOVE_NODE)
        graph.off(EVENT_REMOVE_EDGE)
        graph.off(EVENT_EDGE_CONNECTION)
        graph.off(EVENT_MOVE_NODE)
        graph.fromJSON(modelData.instanceContent)
        afterGraphInit(graph, modelData.instanceContent, () => {
          updateContentById({ branchOrInstanceId: modelData.id, content: JSON.stringify(graph.toJSON()) })
        })
        graph.positionContent('top')
        graph.on(EVENT_ADD_NODE, nodeAdded)
        graph.on(EVENT_SELECTED_NODE, nodeClick)
        graph.on(EVENT_REMOVE_NODE, nodeDel)
        graph.on(EVENT_REMOVE_EDGE, edgeDel)
        graph.on(EVENT_EDGE_CONNECTION, edgeConnected)
        graph.on(EVENT_MOVE_NODE, onSortNode)
      }
    }
  }, [modelData, graph])

  useImperativeHandle(
    ref,
    () => ({
      graph,
      carouselRef,
    }),
    [graph, carouselRef]
  )

  const headerLeft = headerLeftContent || <CommonTitle type="large">{pageTitle}</CommonTitle>

  const headerCenter = <div className="header-center">{toolbar}</div>

  const headerRight = <CommonTitle type="large">节点信息</CommonTitle>

  const contentLeft = <ContainerLayout className="content-left-wrap">
    {
      treePanel ? <Carousel ref={carouselRef} className='content-left-carousel' dots={false} infinite={false}>
          { treePanel }
          { comItems[0] }
      </Carousel> : comItems[0] 
    }
  </ContainerLayout>

  const contentCenter = (
    <ContainerLayout>
      <div id="graph-container" style={{opacity: contentPanel ? 0 : 1 }} ></div>
      { contentPanel }
    </ContainerLayout>
  )

  const contentRight = (
    <div className="top-bottom-layout">
      <div style={{ marginBottom: '16px' }}>
        <ContainerLayout>
          <div className='info-item'>名称: {currentNode && currentNode.data.templateName}</div>
        </ContainerLayout>
      </div>
      {showChildren ? (
        <>
          <div style={{ marginBottom: '16px' }}>
            <CommonTitle type="large">
              { currentNode ? (currentNode.data.typeCode == '8' ? '分支信息' : '用例' ) : '请选择节点'}
            </CommonTitle>
            <div style={{ height: '300px' }}>
              <ContainerLayout >
                <ChildrenTree node={currentNode} changeNodeData={setAttrNodeData} canvasType={modelData ? modelData.canvasType : ''}/>
              </ContainerLayout>
            </div>
          </div>
          <CommonTitle type="large">
            属性{ attrNodeData && attrNodeData.nodeName ? `【${attrNodeData.nodeName}】` : ''}
          </CommonTitle>
        </>
      ) : (
        <CommonTitle>属性</CommonTitle>
      )}
      <div className="flex-1">
        <ContainerLayout>
          <NodeAttrTable projectId={modelData ? modelData.projectId : ''} nodeData={attrNodeData} nameChange={nameChange} />
        </ContainerLayout>
      </div>
    </div>
  )

  return (
    <CanvasPage
      headerLeft={headerLeft}
      headerCenter={headerCenter}
      headerRight={headerRight}
      contentLeft={contentLeft}
      contentCenter={contentCenter}
      contentRight={contentRight}
    >
      <CanvasContextmenu graph={graph} menuConifg={menuConifg} onChangNotes={onChangNotes}/>
    </CanvasPage>
  )
})

FlowCanvas.displayName = 'FlowCanvas'

export default FlowCanvas
